#include "Player.hh"
#include <iostream>
#include <iomanip>
#include "IO.hh"

Player::Player(const std::string& name, unsigned health, unsigned MaxHealth,unsigned attack , unsigned defense, unsigned AP, unsigned gold)
    : name(name), health(health), MaxHealth(MaxHealth), attackPower(attack), defensePower(defense), AP(AP), gold(gold) {
}

void Player::setHealth(unsigned amount){this->health = amount ;}
void Player::setmaxHealth(unsigned amount){this->MaxHealth = amount;}
void Player::setAP(unsigned int AP) {this->AP = AP;}
void Player::setmaxAP(unsigned amount){this->AP = amount;}
void Player::setAttack(unsigned amount) {this->attackPower = amount;}
void Player::setDefense(unsigned amount) {this->defensePower = amount;}

void Player::useAP() {
    if (AP > 0) {
        --AP;  // 减少一个行动点
        std::cout << "You used 1 action point. Remaining: " << AP << "\n";
    } else {
        std::cout << "You don't have enough action points.\n";
    }
}
std::string Player::getName() const {return name;}
unsigned Player::getHealth() const {return health;}
unsigned Player::getMaxHealth() const{return MaxHealth;}
unsigned Player::getAttack() const {return attackPower;}
unsigned Player::getGold() const{return gold;}
unsigned Player::getDefense() const {return defensePower;}
unsigned Player::getAP() const{return AP;}
unsigned Player::getmaxAP() const{return maxAP;}

std::string Player::toString() const {
    return name + " [HP: " + std::to_string(health) + ", attackPower: " + std::to_string(attackPower) + ", defencesPower: "+ std::to_string(defensePower)+ "]";
}

bool Player::isAlive() const {return health > 0;}

void Player::attack(ICharacter& target) {
    unsigned attackpoint;
    if (attackPower >= target.getDefense()/2){
        attackpoint = attackPower - target.getDefense()/2;
    }else{
        attackpoint = 0;
    }
    std::cout << name << " attacks " << target.getName() << " causes " << attackpoint << " damage!\n";
    target -= attackpoint;
}

ICharacter& Player::operator-=(unsigned damage) {
    if (damage >= health) {
        health = 0;
    } else {
        health -= damage;
    }
    std::cout << name << " is attacked " << damage << " damage. Current HP: " << health << "\n";
    return *this;
}

ICharacter& Player::operator*(ICharacter& target) {
    std::cout << name << " and " << target.getName() << " begin a turn-based battle!\n";

    while (this->isAlive() && target.isAlive()) {
        IO::showFightChoice();
        int choice=IO::getNumber();
        switch (choice) {
            case 1: // Attack
                this->attack(target);
                break;
            case 2: // Use Item (placeholder)
                if (inventory.getItems().empty()) {
                    std::cout << "You have no items!\n";
                    continue;//没有物品可被使用时不会进入敌方回合
                }else{
                    this->useItem();
                }
                break;
            case 3: // Check Status
                std::cout << "\n[Player] " << this->toString() << "\n";
                std::cout << "[Enemy]  " << target.toString() << "\n";
                continue; // 不进入敌方回合
            case 4: // Escape
                if (this->tryEscape()){
                    std::cout << name << " ran away from the battle!\n";
                    return *this;
                }else{
                    std::cout << "Player has not enough AP to escape!\n";
                    continue;
                }
                
            default:
                std::cout << "Invalid input. Try again.\n";
                continue;
        }

        // 敌方回合
        if (target.isAlive()) {
            std::cout << "\n--- Enemy Turn ---\n";
            target.attack(*this);
        }
    }

    clearScreen();
    std::cout << "\n*** The Battle Ends! ***\n";
    if (this->isAlive()) {
        std::cout << name << " is victorious!\n";
    } else {
        std::cout << name << " has been defeated...\n";
    }

    return *this;
}


void Player::addItem(const Item& item) { inventory.addItem(item);}
void Player::showInventory() const { inventory.showItems();}
void Player::addGold(unsigned int gold){this->gold += gold;}
void Player::spendGold(unsigned int gold){this ->gold -= gold;}

bool Player::tryEscape() {
    if (AP >= 2){
        AP -= 2;
        return true;
    }else{
        return false;
    }
}

void Player::displayStatus() const {
    std::cout << "\n===== Player State =====\n";
    std::cout << "Name: " << name << "\n";
    std::cout << "Health: " << health << "\n";
    std::cout << "Attack: " << attackPower << "\n";
    if (equippedWeapon) {
        std::cout << "--Weapon: " << equippedWeapon->name << " (" << equippedWeapon->value << " ATK) Level: " <<equippedWeapon->level;
    }else {
        std::cout << " ([No Weapon Equipped])";
    }
    std::cout << "\n";
    std::cout << "Defense: " << defensePower << "\n";
    if (equippedArmor) {
        std::cout << "--Armor: " << equippedArmor->name << " (" << equippedArmor->value << " DEF) Level: " << equippedArmor->level;
    }else {
        std::cout << " ([No Armor Equipped])";
    }
    std::cout << "\n";
    std::cout << "Gold: " << gold << "\n";
}

void Player::equipItem(const Item& item) {
    if (item.type == Item::Type::Weapon) {
        if (!equippedWeapon || item.value > equippedWeapon->value) {
            std::cout << "Equipped new weapon: " << item.name << "\n";
            unsigned tempValue = equippedWeapon ? equippedWeapon->value : 0;
            equippedWeapon = std::make_unique<Item>(item);
            attackPower = attackPower + equippedWeapon->value - tempValue;
        } else {
            std::cout << "The current weapon is stronger or equal.\n";
        }
    } else if (item.type == Item::Type::Armor) {
        if (!equippedArmor || item.value > equippedArmor->value) {
            std::cout << "Equipped new armor: " << item.name << "\n";
            unsigned tempValue = equippedArmor ? equippedArmor->value : 0;
            equippedArmor = std::make_unique<Item>(item);
            defensePower = defensePower + equippedArmor->value - tempValue;
        } else {
            std::cout << "The current armor is stronger or equal.\n";
        }
    }
}

void Player::restoreHealth(unsigned int amount) {
    health += amount;
    if (health > MaxHealth){
        health = MaxHealth;
    }
}

void Player::useItem() {
    if (inventory.getItems().empty()) {
        std::cout << "You have no items!\n";
        return;
    }
    std::cout << "\n-- Items List --\n";
    std::vector<Item>& itmes=inventory.getItems();
    for (size_t i = 0; i < itmes.size(); ++i) {
        std::cout << i + 1 << ". [" << itmes[i].name << "] - " << itmes[i].description << "\n";
    }
    std::cout << "Enter the number of the item which you want to use:  ";
    int choice = IO::getNumber();

    if (choice == 0 || choice > itmes.size()) {
        std::cout << "Cancel use the item.\n";
        return;
    }

    Item item = itmes[choice - 1];
    switch (item.type) {
        case Item::Type::HealPotion:
            restoreHealth(item.value);
            std::cout << "You used [" << item.name << "], recovered " << item.value << " health.\n";
            break;
        case Item::Type::BoostPotion:
            attackPower += item.value;
            std::cout << "You used [" << item.name << "], your attack increased by " << item.value << "!\n";
            break;
        case Item::Type::Weapon:
        case Item::Type::Armor:
            equipItem(item);
            break;
    }

    // 从 items 容器中删除第 (choice - 1) 个元素。
    // Erase the (choice - 1)-th element from the items container (vector).
    itmes.erase(itmes.begin() + (choice - 1));
}

void Player::decreaseMaxHP(int amount){
    MaxHealth -= amount;
    if (MaxHealth < 0){
        MaxHealth = 0;
    }
    if (health > MaxHealth){
        health = MaxHealth;
    }
}

Item* Player::getEquippedWeapon() const {return equippedWeapon.get();}
Item* Player::getEquippedArmor() const {return equippedArmor.get();}
